package com.xydpeng.rpc.protocol.codec;

import com.xydpeng.rpc.protocol.FastRpcProtocol;
import com.xydpeng.rpc.protocol.MsgHeader;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

import static com.xydpeng.rpc.protocol.ObjectPools.fastRpcProtocolRecycler;
import static com.xydpeng.rpc.protocol.ObjectPools.msgHeaderRecycler;

/**
 * @author xydpeng
 * @version v1.0
 * @date: 2023/4/13
 * @description:
 */
public class FastRpcProtocolDecoder extends ByteToMessageDecoder {
    /*
    +---------------------------------------------------------------+
    | 魔数 2byte | 协议版本号 1byte | 序列化算法 1byte | 报文类型 1byte  |
    +---------------------------------------------------------------+
    | 状态 1byte |        消息 ID 8byte     |      数据长度 4byte     |
    +---------------------------------------------------------------+
    |                   数据内容 （长度不定）                          |
    +---------------------------------------------------------------+
    */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int i = in.readableBytes();
        if (i < MsgHeader.PROTOCOL_HEADER_LEN) {
            return;
        }
        in.markReaderIndex();
        short magic = in.readShort();
        if (magic != MsgHeader.MAGIC) {
            throw new IllegalArgumentException("magic number is illegal, " + magic);
        }
        byte version = in.readByte();
        byte serialization = in.readByte();
        byte msgType = in.readByte();
        byte status = in.readByte();
        long requestId = in.readLong();
        int msgLen = in.readInt();
        if (msgLen > in.readableBytes()) {
            in.resetReaderIndex();
            return;
        }
        byte[] data = new byte[msgLen];
        in.readBytes(data);
        MsgHeader header = msgHeaderRecycler.get();
        header.setMagic(magic);
        header.setVersion(version);
        header.setSerialization(serialization);
        header.setStatus(status);
        header.setRequestId(requestId);
        header.setMsgType(msgType);
        header.setMsgLen(msgLen);
        FastRpcProtocol<byte[]> msg = fastRpcProtocolRecycler.get();
        msg.setHeader(header);
        msg.setBody(data);
        out.add(msg);
    }
}
